package com.niiwoo.civet.account.service.dubbo;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.annotation.Service;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.niiwoo.civet.account.dao.entity.AccountBase;
import com.niiwoo.civet.account.dto.common.UserAccountInfoDTO;
import com.niiwoo.civet.account.dto.response.AccountBaseResponse;
import com.niiwoo.civet.account.service.AccountDubboService;
import com.niiwoo.civet.account.service.local.AccountBalanceLocalService;
import com.niiwoo.civet.account.service.local.AccountService;
import com.niiwoo.civet.user.service.OrganizationDubboService;
import com.niiwoo.civet.user.service.UserBasicInfoDubboService;
import com.niiwoo.tripod.base.utils.FutureResponses;
import com.niiwoo.tripod.lanmao.component.LanMaoDirectService;
import com.niiwoo.tripod.lanmao.component.LanMaoSequence;
import com.niiwoo.tripod.lanmao.enums.UserAuthorizationEnum;
import com.niiwoo.tripod.lanmao.enums.UserRoleEnum;
import com.niiwoo.tripod.lanmao.request.CancelUserAuthorizationRequest;
import com.niiwoo.tripod.lanmao.response.CancelUserAuthorizationResponse;
import com.niiwoo.tripod.provider.exception.BizException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

@Slf4j
@Service(version = "1.0.0", validation = "true")
public class AccountDubboServiceImpl implements AccountDubboService {

    @Autowired
    private AccountService accountService;

    @Autowired
    private AccountBalanceLocalService accountBalanceLocalService;

    @Autowired
    private LanMaoDirectService lanMaoDirectService;

    @Autowired
    private LanMaoSequence lanMaoSequence;

    @Reference(version = "1.0.0")
    private UserBasicInfoDubboService userBasicInfoDubboService;

    @Reference(version = "1.0.0")
    private OrganizationDubboService organizationDubboService;


    @Override
    public AccountBaseResponse loadAccountById(Long accountId) {
        AccountBase accountBase = accountService.loadAccountById(accountId);
        return structureAccount(accountBase);
    }

    @Override
    public AccountBaseResponse loadAccountByIdFromMaster(Long accountId) {
        AccountBase accountBase = accountService.loadAccountByIdFromMaster(accountId);
        return structureAccount(accountBase);
    }

    @Override
    public AccountBaseResponse loadAccountByAccountNo(String accountNo) {
        AccountBase accountBase = accountService.loadAccountByAccountNo(accountNo);
        return structureAccount(accountBase);
    }

    @Override
    public AccountBaseResponse getNiiwooAccount(String userId, UserRoleEnum role) {
        AccountBase accountBase = accountService.getNiiwooAccount(userId, role);
        if (Objects.isNull(accountBase)) {
            return null;
        }

        return structureAccount(accountBase);
    }

    @Override
    public AccountBaseResponse loadNiiwooAccount(String userId, UserRoleEnum role) {
        AccountBase accountBase = accountService.loadNiiwooAccount(userId, role);
        return structureAccount(accountBase);
    }

    @Override
    public AccountBaseResponse loadActivedNiiwooAccount(String userId, UserRoleEnum role) {
        AccountBase accountBase = accountService.loadNiiwooAccount(userId, role);
        if (Byte.valueOf("0").equals(accountBase.getImportUserActiva())) {
            throw new BizException("ACC10003");// 存管账户未激活
        }

        return structureAccount(accountBase);
    }

    @Override
    public List<AccountBaseResponse> listNiiwooAccountByUserId(String userId){
        List<AccountBase> accountBaseList = accountService.listNiiwooAccountByUserId(userId);
        return  accountBaseList.stream().map(accountBase -> structureAccount(accountBase)).collect(Collectors.toList());
    }

    @Override
    public List<AccountBaseResponse> listNiiwooAccountByUserId(String userId,String orgId){
        List<AccountBase> accountBaseList = accountService.listNiiwooAccountByUserId(userId,orgId);
        return  accountBaseList.stream().map(accountBase -> structureAccount(accountBase)).collect(Collectors.toList());
    }

    @Override
    public UserAccountInfoDTO queryNiiwooAccountFlat(String userId) {
        List<AccountBase> accountBases = accountService.listNiiwooAccountByUserId(userId);
        UserAccountInfoDTO userAccountInfoDTO = new UserAccountInfoDTO();
        if (accountBases != null && accountBases.size() > 0) {
            accountBases.forEach(p -> {
                if (UserRoleEnum.INVESTOR.getValue().equals(p.getAccountRole())) {
                    userAccountInfoDTO.setIsFreeInvest(p.getTender());
                    userAccountInfoDTO.setAccountIdInvestor(p.getId());
                    userAccountInfoDTO.setAccountNoInvestor(p.getAccountNo());
                    userAccountInfoDTO.setInvestorActive(p.getImportUserActiva());
                    userAccountInfoDTO.setBalanceAmountInvestor(p.getAvailableAmount());
                } else if (UserRoleEnum.BORROWERS.getValue().equals(p.getAccountRole())) {
                    userAccountInfoDTO.setAccountIdBorrower(p.getId());
                    userAccountInfoDTO.setAccountNoBorrower(p.getAccountNo());
                    userAccountInfoDTO.setBorrowerActive(p.getImportUserActiva());
                    userAccountInfoDTO.setBalanceAmountBorrower(p.getAvailableAmount());
                } else if (UserRoleEnum.GUARANTEECORP.getValue().equals(p.getAccountRole())) {
                    userAccountInfoDTO.setAccountIdGuarantee(p.getId());
                    userAccountInfoDTO.setAccountNoGuarantee(p.getAccountNo());
                    userAccountInfoDTO.setGuaranteeActive(p.getImportUserActiva());
                    userAccountInfoDTO.setBalanceAmountGuarantee(p.getAvailableAmount());
                }
            });
        }
        return userAccountInfoDTO;
    }


    @Override
    public AccountBaseResponse getOrgAccount(String userId, String orgId) {
        AccountBase accountBase = accountService.getOrgAccount(userId, orgId);
        if (Objects.isNull(accountBase)) {
            return null;
        }

        return structureAccount(accountBase);
    }

    @Override
    public AccountBaseResponse loadOrgAccount(String userId, String orgId) {
        AccountBase accountBase = accountService.loadOrgAccount(userId, orgId);
        return structureAccount(accountBase);
    }

    @Override
    public AccountBaseResponse loadActivedOrgAccount(String userId, String orgId) {
        AccountBase accountBase = accountService.loadOrgAccount(userId, orgId);
        if (Byte.valueOf("0").equals(accountBase.getImportUserActiva())) {
            throw new BizException("ACC10003");// 存管账户未激活
        }

        return structureAccount(accountBase);
    }

    @Override
    public void checkAccountAuth(Long accountId, Set<UserAuthorizationEnum> authorizations) {
        AccountBase accountBase = accountService.loadAccountById(accountId);
        for (UserAuthorizationEnum authorization : authorizations) {
            if (!hasAuthorization(accountBase, authorization)) {
                throw new BizException("ACC11001", authorization.getDesc());
            }
        }
    }

    @Override
    public void notifyEnabledUserAuthorization(String accountNo, String requestNo, Set<UserAuthorizationEnum> authorizations) {
        accountService.enableUserAuthrozition(accountNo, authorizations);
    }

    @Override
    public void disableUserAuthorization(String accountNo, Set<UserAuthorizationEnum> authorizations) {
        AccountBase account = accountService.loadAccountByAccountNo(accountNo);
        for (UserAuthorizationEnum authorization : authorizations) {
            if (!hasAuthorization(account, authorization)) {
                throw new BizException("ACC11001", authorization.getDesc());
            }
        }
        CancelUserAuthorizationRequest request = new CancelUserAuthorizationRequest();
        request.setPlatformUserNo(account.getAccountNo());
        request.setRequestNo(lanMaoSequence.getRequestNo());
        request.setAuthList(Joiner.on(",").skipNulls().join(authorizations.stream().map(UserAuthorizationEnum::name).collect(Collectors.toSet())));
        CompletableFuture<CancelUserAuthorizationResponse> future = lanMaoDirectService.cancelUserAuthorization(request);
        CancelUserAuthorizationResponse response = FutureResponses.get(future);
        List<UserAuthorizationEnum> authorizationEnums = Splitter.on(",").splitToList(response.getAuthList()).stream()
                .map(UserAuthorizationEnum::valueOf)
                .collect(Collectors.toList());
        accountService.disableUserAuthorization(account.getId(), authorizationEnums);
    }



//
//
//    /**
//     * 根据用户userId查询所有存管账号信息（余额和账号）
//     * 我-首页查询,包含财富总额
//     *
//     * @param userId
//     * @return
//     * @auther bincun
//     */
//    @Override
//    public UserAccountInfoDTO queryUserAccountInfoIndex(String userId) {
//        UserAccountInfoDTO userAccountInfoDTO = accountBalanceLocalService.queryUserAccountInfo(userId);
//        //用户总余额+待收本金+待收利息+投资冻结
//        userAccountInfoDTO.setTotalWealthAmount(moneyTotalLocalService.queryMoneyTotal(userId).getAmountTotal());
//        return userAccountInfoDTO;
//    }
//

//

//
    @Override
    public BigDecimal getTotalInvestAmount(List<String> userIds) {
        return accountBalanceLocalService.getTotalInvestAmount(userIds);

    }

    private AccountBaseResponse structureAccount(AccountBase accountBase) {
        AccountBaseResponse result = new AccountBaseResponse();
        result.setAccountId(accountBase.getId());
        result.setUserId(accountBase.getUserId());
        result.setOrgId(accountBase.getOrgId());
        result.setAccountRole(accountBase.getAccountRole());
        result.setAccountNo(accountBase.getAccountNo());
        result.setAvailableAmount(accountBase.getAvailableAmount());
        result.setImportUserActiva(accountBase.getImportUserActiva());
        result.setAccountType(accountBase.getAccountType());
        result.setTender(accountBase.getTender());
        result.setRepayment(accountBase.getRepayment());
        result.setCreditAssignment(accountBase.getCreditAssignment());
        result.setCompensatory(accountBase.getCompensatory());
        result.setWithdraw(accountBase.getWithdraw());
        result.setRecharge(accountBase.getRecharge());
        return result;
    }

    private boolean hasAuthorization(AccountBase accountBase, UserAuthorizationEnum authorization) {
        switch (authorization) {
            case TENDER:
                return 1 == accountBase.getTender();
            case REPAYMENT:
                return 1 == accountBase.getRepayment();
            case CREDIT_ASSIGNMENT:
                return 1 == accountBase.getCreditAssignment();
            case COMPENSATORY:
                return 1 == accountBase.getCompensatory();
            case WITHDRAW:
                return 1 == accountBase.getWithdraw();
            case RECHARGE:
                return 1 == accountBase.getRecharge();
            default:
                return false;
        }
    }
    
}
